雖然一開始說 Vue 因為有 Single File Component ,所以要 Server Side Render 可能會碰到需要用 bundler 的情況,不過用 React 時,在最後碰到圖片時還是非要用 hook require 的方式來解決,實際上早點用 bundler 或許也不用做到這樣,回到正題,雖然我個人是 React 派的,但 Vue 在某些方面真的做的很好,這篇也會提到
這邊提到的只是就這個系列而言,我沒有要來寫一篇 React 跟 Vue 的比較文 (雖然我寫過,但那是很久以前的事了)
action
與 mutation
還記得我們把 Redux 的 actions 全部保存下來嗎?但實際上有些只是用來觸發 AJAX 之類的非同步的工作用的 action ,並不是真的要改變資料,而在 Vuex 中, action
跟 mutation
有明確的工作分別, mutation
才能改變資料,如果用 Vuex 就只要保存 mutation
就夠了
或許知道這個東西的人可能比較少, vue-router 的 middleware 是非同步的,所以 vue-router 從網址改變,到實際跳轉網頁前還可以做一些事,也可以反悔,取消掉使用者的跳轉, react-router 則是要跳轉完才可以開始動作,不知道你有沒有想到這東西可以用在哪?可以用在抓資料上,只要在 middleware 中加入抓資料的程式碼,我們也不用自己先把資料抓完才開始 render 了,只要等到 vue-router 通知我們網址已經轉過去了 (正常情況下應該是沒有機會用到 router.onReady
這個 API 吧)
這個其實有好有壞,壞處之前講過了,因為一定要編譯,所以初期會多出 bundler 要設定,不過好處是除了現有的 html
, script
跟 style
,它可以加入自訂的區塊,這個功能也很少用,不過你可以看看 Gridsome ,它就用這個功能來放 page query 跟 static query ,雖然 page query 沒有這個問題,但 static query 是要用 babel 從原始碼中抽出來的,它也是正常的程式碼的一部份,要從一份原始碼中將其區格出來也是一個麻煩,雖然差別我是沒有覺得到很大
Vue 基本的 SSR 該說是大同小異嗎?同樣的也是 renderToString
跟 renderToStream
,不過不一樣的是,該說 Vue 的定位真不愧是框架, html 的 template 也可以由它產生, Vuex 的初始 state 也會幫你加入產生的 html 中 (前題是如果你有提供的話)
Vue 的元件其實有個 API 叫 serverPrefetch
,它會在 Server 端被執行,讓你可以在 Server 端呼叫 Vuex 的 action ,從而把資料存進去:
<script>
import {mapActions} from 'vuex'
export default {
serverPrefetch() {
return this.fetchData()
},
methods: {
...mapActions(['fetchData']),
},
}
</script>
這個 API Vue 也會自動的等待它完成,所以在 Vue 中,完全不用擔心之前碰到的什麼 render 過程是同步的問題,另外 Vue 的元件上還有個屬性:
<script>
export default {
// created 跟 beforeCreate 才會在 server 端執行,但 beforeCreate 時 Vue 的 instance 又還沒建好
created() {
// 這個物件會跟 render 時傳入的一個物件是同一個,所以可以用這邊傳資料回去給 render 的程式
this.$ssrContext.foo = 42
}
}
</script>
在 render 時 Vue 要傳入一個 object :
import { createRenderer } from 'vue-server-renderer'
const renderer = createRenderer()
// 這就會是上面的 `$ssrContext`
const context = {}
// 這樣就能取得完整的 html
const html = await renderer.renderToString(app, context)
下一篇我們再來實際用一次 Vue 的 SSG